﻿using CAPlugin.Interface;
using HBCA_SOFSEALLib;
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using CAPlugin.Util;
using System.IO;
using System.Drawing.Imaging;

namespace CAPlugin
{
    public partial class LoginForm : Form
    {
        public string OutFile { get; set; }
        public string ActionName { get; set; }
        public IServer Server { get; set; }
        public IClient Client { get; set; }
        public SealClass Seal { get; set; }
        public string HashMethod { get; set; }
        public string DefaultCert { get; set; }

        public LoginForm()
        {
            InitializeComponent();
        }

        private void LoginForm_Load(object sender, EventArgs e)
        {
            string errMsg;
            HashMethod = ConfigurationManager.AppSettings["hash_method"].ToString();
            if (!GetUserList(out errMsg))
            {
                MessageBox.Show("获取用户列表失败：" + errMsg);
            }
            else
            {
                cb_ca_user.SelectedIndex = 0;
            }
        }

        private bool GetUserList(out string errMsg)
        {
            bool isSuccess = false;
            errMsg = string.Empty;
            cb_ca_user.Text = string.Empty;
            cb_ca_user.Items.Clear();
            Client.SetCertAppPolicy("SIGN");
                 // 证书过滤策略  只要签名证书
            Client.SetHashMethod(HashMethod);

            string userList = Client.GetUserList();

            if (userList==null || userList.Length==0)
            {
                errMsg = "没有检测到证书，请插入Key！";
                return isSuccess;
            }
            string[] users = userList.Split(new string[] { "&&&" }, StringSplitOptions.None);
            cb_ca_user.BeginUpdate();
            foreach (string user in users)
            {
                string[] attrs = user.Split(new string[] { "||" }, StringSplitOptions.None);
                string certId = attrs[0];
                string DN = attrs[1];
                string certB64 = attrs[3];
                UkeyInfo info = new UkeyInfo(certId, DN);
                info.CertB64 = certB64;
                cb_ca_user.Items.Add(new VisualDataItem<UkeyInfo>(info, info.DN));
            }
            cb_ca_user.EndUpdate();
            isSuccess = true;

            return isSuccess;
        }

        private bool Login(out string errMsg)
        {
            bool isSuccess = false;
            errMsg = string.Empty;

            try
            {
                int iRet = -1;
                if (cb_ca_user.SelectedItem == null)
                {
                    errMsg = "尚未选择CA用户";
                    return isSuccess;
                }

                UkeyInfo currUkey = (cb_ca_user.SelectedItem as VisualDataItem<UkeyInfo>).Tag;
                string certId = string.Empty;
                if (ActionName == "unLoginSign")
                {
                    certId = DefaultCert;
                }
                else
                {
                    certId= currUkey.CertId;
                }
                string password = tb_password.Text;
#if DEBUG
                Console.WriteLine(string.Format("CertID:{0},password:{1}",certId,password));
#endif
                    iRet = Client.Login(certId, password);
                    if (iRet != 0)
                    {
                        //errMsg = "密码错误！";
                        errMsg = Client.GetErrorMsg();
                        return isSuccess;
                    }

                // 生成随机10位整数
                string inData = Client.GenRandom(10);
#if DEBUG
                Console.WriteLine("hashMethod:"+HashMethod);
#endif
                Client.SetHashMethod(HashMethod);

                // 0、Attach  1、Detach
                Client.SetP7SignMode(1);
#if DEBUG
                Console.WriteLine(string.Format("CertID:{0},inData:{1}", certId, inData));
#endif
                string signedVaule = Client.SignDataByP7(certId, inData);

                // 服务端验签
                Server.SetP7SignMode(1);
                Server.SetHashMethod(HashMethod);
                iRet = Server.VerifyDetachSignedData(signedVaule, inData);

                if (iRet != 0) // 验签失败
                {
                    errMsg = string.Format("ServerSdk-{0}, ClientSdk-{1}", Server.GetErrorMsg(),
                                                                      Client.GetErrorMsg());
                    return isSuccess;
                }

                // 验签成功
                File.WriteAllText(OutFile, string.Empty); // 清空文件内容
                if (ActionName == "read")
                {
#if DEBUG
                    Console.WriteLine("read操作");
#endif
                    File.WriteAllText(OutFile, certId,Encoding.UTF8);
                    
#if DEBUG
                    Console.WriteLine("Pin加密后："+ encryptedPin);
                    Console.Write("Pin码已加密保存至文件！");
                    Console.WriteLine("read 成功！ CertID已写入："+OutFile);
#endif
                }
                if (ActionName == "bind")// bind
                {
#if DEBUG
                    Console.WriteLine("bind操作");
#endif
                    string toFile = string.Empty;
                    string imageB64 = Seal.SOF_GetKeyPictureEx(certId,"");
                    if (string.IsNullOrEmpty(imageB64))
                    {
                        imageB64 = "NULL";
                    }
                    else
                    {
                        // 编码是为了存储和传输的，一旦打开文件了，.net 内部已经帮你解压了(解码了)，
#if DEBUG
                        Console.WriteLine("已获取签章图片Base64");
#endif
                        byte[] imageBytes = Convert.FromBase64String(imageB64);
                        // 创建内存流
                        using (MemoryStream ms = new MemoryStream(imageBytes))
                        {
                            // 从内存流加载图片
                            using (Image image = Image.FromStream(ms))
                            {
                                string filePath = "output.jpg";
                                if (File.Exists(filePath))
                                { 
                                    File.Delete(filePath);
                                }
                                using (MemoryStream saveMs = new MemoryStream())
                                {
                                    //  JPG 格式，保存到内存流
                                    image.Save(saveMs, ImageFormat.Jpeg);
                                    image.Save(filePath, ImageFormat.Jpeg);
                                    saveMs.Position = 0;
                                    byte[] jpgBytes = saveMs.ToArray();
                                    imageB64 = Convert.ToBase64String(jpgBytes);
#if DEBUG
                                    Console.WriteLine("图片已保存为：" + filePath);
#endif
                                }
                            }
                        }
                    }

                    toFile = certId + "\r\n" + imageB64;

                    try
                    {
                        using (StreamWriter writer = new StreamWriter(OutFile, false, Encoding.UTF8))
                        {
                            writer.Write(toFile);
#if DEBUG
                            Console.WriteLine("证书序列号、签章图片Base64已保存至输出文件");
#endif
                        }
                    }
                    catch (Exception e)
                    {
                        string fileWriteErrMsg = "文件写入时发生错误：" + e.Message;
                        throw new Exception(fileWriteErrMsg);
                    }
#if DEBUG
                    Console.WriteLine("bind操作成功！");
#endif
                }
                string encryptedPin = Encrypt.EncryptString(password);
                File.WriteAllText("Pin.txt", encryptedPin, Encoding.UTF8);
                isSuccess = true;
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                return isSuccess;
            }
            return isSuccess;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string errMsg;
            if (!Login(out errMsg))
            {
                MessageBox.Show("证书登录失败:" + errMsg, "登录失败");
            }
            else
            {
                DialogResult = DialogResult.OK;
                Close();
            }
        }

        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void label2_Click(object sender, EventArgs e)
        {

        }
    }
}
